#include "stdafx.h"
#include <algorithm>
#include <fstream>
#include <boost/bind.hpp>
#include "node_record_manager.h"
namespace Utility {
    node_record_manager::node_record_manager() :
        m_valid_record_id(0) {
    }

    void node_record_manager::remove_record(int id) {
        m_record_bits.set(id) ;
    }

    void node_record_manager::remove_range(int begin, int end) {
        for(int i = begin ; i < end ; ++i)
            m_record_bits.set(i) ;
    }
    
    void node_record_manager::conbine_records(const node_record_manager& other) {
        std::for_each(other.m_records.begin(), other.m_records.end(),
                      boost::bind(&node_record_manager::buy_record_from_other,
                                  this,
                                  _1)) ;
    }
    void node_record_manager::buy_record_from_other(const node_record_type& type) {
        push_record(type.second) ;
    }
    bool node_record_manager::read_from_file(const char* file_name) {
        std::fstream filein(file_name) ;
        try {
            m_records.clear() ;
            int version ;
            filein >> version ;
            if(version > 0) m_valid_record_id = version ;
            else
                filein >> m_valid_record_id ;
            for(int i = 0 ; i < m_valid_record_id ; ++i) {
                normal_number_range n ;
                float x, y ;
                int round = 0;
                filein >> n ;
                filein >> x >> y ;
                if(version < 0) filein >> round ;
                m_records.push_back(std::make_pair(i,boost::make_tuple(n,x,y,round))) ;
            }
            filein.close() ;
            return true ;
        } catch(...) {
            filein.close() ;
            return false ;
        }
    }

    bool node_record_manager::write_to_file(const char* file_name) {
        std::fstream fileout(file_name, std::ios::trunc | std::ios::out) ;
        try {
            fileout << -1 << std::endl ;
            fileout << m_records.size() << std::endl ;
            for(size_t i = 0 ; i < m_records.size() ; ++i) {
                fileout << boost::get<NODE_POSITION>(m_records[i].second) << std::endl ;
                fileout << boost::get<NODE_X>(m_records[i].second) << std::endl ;
                fileout << boost::get<NODE_Y>(m_records[i].second) << std::endl ;
                fileout << boost::get<NODE_ROUND>(m_records[i].second) << std::endl ;
            }
            fileout.close() ;
            return true ;
        } catch(...) {
            fileout.close() ;
            return false ;
        }
    }
        

    void node_record_manager::push_record(const node_record_value_type& value) {
        m_records.push_back(std::make_pair(m_valid_record_id++, value)) ;
    }

    void node_record_manager::make_value_valid(manager_record_vector::reference value) {
        value.first = m_valid_record_id++ ;
    }

    bool node_record_manager::need_remove(const node_record_type& node) {
        return m_record_bits.test(node.first) ;
    }

    void node_record_manager::rerange() {
        m_records.erase(std::remove_if(m_records.begin(), m_records.end(),
                                       boost::bind(&node_record_manager::need_remove, this,
                                                   _1)), m_records.end()) ;
        m_record_bits.reset() ;
        std::sort(m_records.begin(),
                  m_records.end()) ;
        m_valid_record_id = 0 ;
        std::for_each(m_records.begin(), m_records.end(),
                      boost::bind(&node_record_manager::make_value_valid,
                                  this, _1)) ;
    }

    node_record_value_type& node_record_manager::node_info(int id) {
        manager_record_vector::iterator it = std::find(m_records.begin(),
                                                       m_records.end(),
                                                       std::make_pair(id, normal_number_range())) ;
        if(it == m_records.end()) throw "error" ;
        return (*it).second ;
    }

    void node_record_manager::add_record(int id, const normal_number_range& n,
                                         float x, float y, int level) {
        add_record(id, boost::make_tuple(n,x,y,level)) ;
    }

    void node_record_manager::push_record(const normal_number_range& n,
                                          float x, float y, int level) {
        push_record(boost::make_tuple(n,x,y,level)) ;
    }
    void node_record_manager::add_record(int id,
                                         const node_record_value_type& value) {
        manager_record_vector::iterator it = std::find(m_records.begin(),
                                                       m_records.end(),
                                                       std::make_pair(id, value)) ;
        if(it == m_records.end()) {
            m_records.push_back(std::make_pair(id, value)) ;
            m_valid_record_id = id ;
        } else {
            m_records.insert(it + 1, std::make_pair(id, value)) ;
            rerange() ;
        }
    }

}
